﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace FileCopy
{
    [XmlRoot("Item")]
    public class f_Item
    {
        private string name;
        [CategoryAttribute("名称"), DisplayName("任务名称")]
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        [CategoryAttribute("参数设置"), DisplayName("源路径")]
        [XmlElement("Src")]
        public string DirectoryPath { get; set; }

        private List<f_Directory> destPaths;
        public f_Directory[] DestPaths
        {
            get
            {
                if (destPaths == null)
                    return null;
                return destPaths.ToArray();
            }
            set
            {
                destPaths = new List<f_Directory>();
                if (value != null)
                    destPaths.AddRange(value);
            }
        }

        public void AddDestPath(f_Directory dir)
        {
            if (destPaths == null)
                destPaths = new List<f_Directory>();
            destPaths.Add(dir);
        }

        public void RemoveDestPath(f_Directory dir)
        {
            destPaths.Remove(dir);
        }

        [XmlIgnore]
        public bool IsValid
        {
            get
            {
                if (IsExists && DestPaths != null && DestPaths.Length > 0 && !string.IsNullOrEmpty(DirectoryPath))
                    return true;
                return false;
            }
        }

        [XmlIgnore]
        [CategoryAttribute("其他"), DescriptionAttribute("源文件夹是否存在"), DisplayName("源路径存在")]
        public bool IsExists
        {
            get
            {
                if (string.IsNullOrEmpty(this.DirectoryPath))
                    return false;
                return Directory.Exists(this.DirectoryPath);
            }
        }

        [XmlIgnore]
        [CategoryAttribute("开关")]
        public bool Enabled
        {
            get { return enabled; }
            set
            {
                if (!value)
                {
                    enabled = value;
                    Stop();
                }
                else if (Start())
                {
                    enabled = value;
                }
            }
        }
        private bool enabled = false;

        private bool running = false;
        [CategoryAttribute("其他"), DescriptionAttribute("是否删除源文件"), DisplayName("删除源文件")]
        public bool DelOld { get; set; }

        private FileSystemWatcher fileSystemWatcher;
        private bool includeSubdirectories = false;
        /// <summary>
        /// 获取或设置一个值，该值指示是否监视指定路径中的子目录。
        /// </summary>
        [DefaultValue(false)]
        [CategoryAttribute("参数设置"), DescriptionAttribute("是否监视指定路径中的子目录"), DisplayName("包含子目录")]
        public bool IncludeSubdirectories
        {
            get { return includeSubdirectories; }
            set { includeSubdirectories = value; }
        }

        private string filter = "*.*";
        /// <summary>
        /// 获取或设置筛选字符串，用于确定在目录中监视哪些文件。
        /// </summary>
        [DefaultValue("*.*")]
        [CategoryAttribute("参数设置"), DescriptionAttribute("设置筛选字符串"), DisplayName("筛选串")]
        public string Filter
        {
            get { return filter; }
            set { filter = value; }
        }

        [XmlIgnore]
        private System.Timers.Timer timer;

        public bool Start()
        {
            if (!IsExists || this.DestPaths == null || this.DestPaths.Length == 0)
            {
                MessageBox.Show("路径设置无效...", "提示");
                return false;
            }
            else
            {
                foreach (f_Directory path in this.DestPaths)
                {
                    if (!Directory.Exists(path.DestDirectory))
                    {
                        Directory.CreateDirectory(path.DestDirectory);
                    }
                }

                if (DelOld)
                {
                    timer = new System.Timers.Timer() { Interval = 10 * 60 * 1000, AutoReset = true, Enabled = running };
                    timer.Elapsed += timer_Elapsed;
                    timer.Start();
                }
                running = true;

                fileSystemWatcher = new FileSystemWatcher() { Path = this.DirectoryPath, NotifyFilter = NotifyFilters.FileName, Filter = this.Filter, IncludeSubdirectories = this.IncludeSubdirectories };
                fileSystemWatcher.Created += fileSystemWatcher_Created;
                fileSystemWatcher.EnableRaisingEvents = running;
                return true;
            }
        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                string[] filePaths = Directory.GetFiles(this.DirectoryPath, this.Filter, IncludeSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
                if (filePaths != null)
                {
                    foreach (string path in filePaths)
                    {
                        if (File.Exists(path))
                        {
                            FileInfo file = new FileInfo(path);
                            if (file.LastWriteTime < DateTime.Now.AddMinutes(-10))
                                File.Delete(path);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ExceptionManager.TraceWrite(ex.Message, "删除文件");
            }
        }

        public void Stop()
        {
            running = false;
            if (DelOld)
            {
                timer.Stop();
                timer.Dispose();
            }
            if (fileSystemWatcher != null)
            {
                fileSystemWatcher.EnableRaisingEvents = running;
                fileSystemWatcher.Dispose();
            }
        }

        private void fileSystemWatcher_Created(object sender, FileSystemEventArgs e)
        {
            if (e.ChangeType == WatcherChangeTypes.Created)
            {
                DateTime time = DateTime.Now;
                Console.WriteLine(e.FullPath);
                string src = e.Name;
                foreach (f_Directory path in this.DestPaths)
                {
                    f_File file = new f_File(e.FullPath, path.DestDirectory, time);
                    if (path.Enabled && path.IsFileValid(file.FileName))
                    {
                        //ThreadPool.QueueUserWorkItem(CopyTo, file);
                        Thread thread = new Thread(file.CopyTo);
                        thread.Start();
                    }
                }
            }
        }

        private void CopyTo(object file)
        {
            try
            {
                f_File _file = (f_File)file;
#if !CMD
                File.Copy(_file.SrcFileFullName, _file.DesFileFullName, true);
#else
                string cmd = string.Format("copy /y {0} {1}", _file.SrcFileFullName, _file.DesFileFullName);
                using (System.Diagnostics.Process process = new System.Diagnostics.Process())
                {
                    process.StartInfo.FileName = "cmd.exe";
                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.RedirectStandardInput = true;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.StartInfo.RedirectStandardError = true;
                    process.StartInfo.CreateNoWindow = true;
                    process.Start();
                    process.StandardInput.WriteLine(cmd);
                    process.StandardInput.WriteLine("exit");
                    Console.WriteLine(process.StandardOutput.ReadToEnd());
                    process.Close();
                }
#endif
            }
            catch (Exception ex)
            {
                ExceptionManager.TraceWrite(ex.Message, this.DirectoryPath);
            }
        }

        public override string ToString()
        {
            return Name;
        }

        public void Update(f_Item item)
        {

        }
    }
}
